﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Newtonsoft.Json;
using System.Web;

namespace Bowerbird.Api.Dtos
{
    public class ApiWrapper
    {
        protected static string IDENTITY_PROVIDER_CLAME_TYPE = @"http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider";
        protected static string NAME_IDENTIFIER_CLAME_TYPE = @"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
        protected static string NAME_CLAIM_TYPE = @"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
        protected static string EXPIRATION_CLAIM_TYPE = @"http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration";
        protected static string EMAIL_ADDRESS_CLAIM_TYPE = @"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
        protected static string ACCESS_TOKEN_CLAIM_TYPE = @"http://www.facebook.com/claims/AccessToken";

        public static User LogIn(string identityProvider, string nameIdentifier, string name)
        {
            var operationUri = "http://localhost/bowerbird.api/users/login";

            var webClient = new WebClient();

            // Content-Type
            webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json");

            // Authorization
            Claims claims = TryReadClaims();

            webClient.Headers.Add(HttpRequestHeader.Authorization, JsonConvert.SerializeObject(claims));

            var data = new
            {
                identityProvider = identityProvider,
                nameIdentifier = nameIdentifier,
                name = name
            };
            
            // Make the call
            var response = webClient.UploadString(operationUri, "POST", JsonConvert.SerializeObject(data));

            // Json to object
            var result = JsonConvert.DeserializeObject<User>(response);

            return result;
        }

        public static User EditUserProfile(User user)
        {
            var operationUri = "http://localhost/bowerbird.api/user/edit";

            var webClient = new WebClient();

            // Content-Type
            webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json");

            // Authorization
            Claims claims = TryReadClaims();

            webClient.Headers.Add(HttpRequestHeader.Authorization, JsonConvert.SerializeObject(claims));

            // Make the call
            var response = webClient.UploadString(operationUri, "POST", JsonConvert.SerializeObject(user));

            // Json to object
            var result = JsonConvert.DeserializeObject<User>(response);

            return result;

        }


        private static Claims TryReadClaims()
        {
            Claims claims = new Claims();

            var identity = (Microsoft.IdentityModel.Claims.ClaimsIdentity)HttpContext.Current.User.Identity;

            // Identity Provider
            var claim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(IDENTITY_PROVIDER_CLAME_TYPE));
            if (claim != null)
                claims.IdentityProvider = claim.Value;
            else
                throw new UnauthorizedAccessException("Cannot read IdentityProvider claim.");

            // Name Identifier
            claim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(NAME_IDENTIFIER_CLAME_TYPE));
            if (claim != null)
                claims.NameIdentifier = claim.Value;
            else
                throw new UnauthorizedAccessException("Cannot read NameIdentifier claim.");

            // Name
            claim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(NAME_CLAIM_TYPE));
            if (claim != null)
                claims.Name = claim.Value;

            // Email Address
            claim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(EMAIL_ADDRESS_CLAIM_TYPE));
            if (claim != null)
                claims.Email = claim.Value;

            // Access Token
            claim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(ACCESS_TOKEN_CLAIM_TYPE));
            if (claim != null)
                claims.AccessToken = claim.Value;

            // Expiration
            claim = identity.Claims.SingleOrDefault(c => c.ClaimType.Equals(EXPIRATION_CLAIM_TYPE));
            if (claim != null)
                claims.Expiration = claim.Value;

            return claims;
        }

        private struct Claims
        {
            public string IdentityProvider { get; set; }
            public string NameIdentifier { get; set; }
            public string Name { get; set; }
            public string Email { get; set; }
            public string AccessToken { get; set; }
            public string Expiration { get; set; }
        }

    }
}
